/**
 * 
 */
package edu.vanderbilt.vshare.multicast;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * class containing generic utility methods
 * 
 * @author jedmondson
 *
 */
public class Utility {

	/**
	 * copies one byte array into another. Performs bounds checking on both src and dest.
	 * 
	 * @param     src                source array that is being copied
	 * @param     src_offset         offset into src to start copying from
	 * @param     dest               target array that is receiving the copy
	 * @param     dest_offset        offset into dest to start writing to
	 * @return                       reference to dest
	 */
	
	public static byte [] copy (byte[] src, int src_offset, byte [] dest, int dest_offset)
	{
		for (; src_offset < src.length && dest_offset < dest.length; 
		       ++src_offset, ++dest_offset)
			dest[dest_offset] = src[src_offset];
		
		return dest;
	}

	/**
	 * helper function for trimming a zero-padded String down to size
	 * 
	 * @param     input              zero padded string
	 * @return                       new String without the zero padding
	 */
	
	public static String trimZeros (String input)
	{
		String [] valid = input.split("\0");
		return valid[0];
	}

	/**
	 * fill an array of byte arrays with nulls
	 * 
	 * @param     array              array of byte arrays to fill
	 */
	
	public static void fillNulls (byte [][] array)
	{
		for (int i = 0; i < array.length; ++i)
		{
			array[i] = null;
		}
	}

	/**
	 * fill a byte array with nulls
	 * 
	 * @param     array              byte array to fill
	 * @return                       reference to byte array
	 */
	
	public static  byte [] fillNulls (byte [] array)
	{
		return fillNulls (array, 0);
	}

	/**
	 * fill a byte array from some offset with nulls
	 * 
	 * @param     array              byte array to fill
	 * @param     offset             offset into the byte array to begin filling at
	 * @return                       reference to byte array
	 */
	
	public static  byte [] fillNulls (byte [] array, int offset)
	{
		return fillWithValue(array, offset, (byte)0);
	}

	/**
	 * fill a byte array with some value
	 * 
	 * @param     array              byte array to fill
	 * @param     value              value to fill in
	 * @return                       reference to byte array
	 */
	
	public static  byte [] fillWithValue (byte [] array, byte value)
	{
		return fillWithValue(array, 0, value);
	}

	/**
	 * fill a byte array with some value from an offset
	 * 
	 * @param     array              byte array to fill
	 * @param     offset             offset into the byte array to begin filling at
	 * @param     value              value to fill in
	 * @return                       reference to byte array
	 */
	
	public static byte [] fillWithValue (byte [] array, int offset, byte value)
	{
		for (int i = offset; i < array.length; ++i)
			array[i] = value;
		
		return array;
	}

	/**
	 * convert a string ip into an encoded int version
	 * 
	 * @param     ip                 String ip
	 * @return                       new version of ip
	 */
	
	public static int ipToInt (String ip)
	{
		return bytesToInt(ipToBytes(ip));
	}

	/**
	 * convert a string ip into a byte array
	 * 
	 * @param     ip                 String ip
	 * @return                       new version of ip
	 */
	
	public static byte[] ipToBytes (String ip)
	{
		try
		{
			InetAddress my_addr = InetAddress.getByName(ip);
			return my_addr.getAddress();
		}
		catch (UnknownHostException e)
		{
			e.printStackTrace();
		}
		
		return null;
	}

	/**
	 * convert a byte address into an encoded int
	 * 
	 * @param     address            String ip
	 * @return                       new version of ip
	 */
	
	public static int bytesToInt (byte [] address)
	{
		ByteArrayInputStream bis = new ByteArrayInputStream(address);  
		DataInputStream dis = new DataInputStream(bis);  
		
		int encoded = 0;
		
		try {
			encoded = dis.readInt();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		
		return encoded;
	}

	/**
	 * convert an integer encoded ip into a byte array
	 * 
	 * @param     encoded            integer encoded ip address
	 * @return                       new version of ip
	 */
	
	public static byte [] intToBytes (int encoded)
	{
		ByteArrayOutputStream bos = new ByteArrayOutputStream(4);  
		DataOutputStream dos = new DataOutputStream(bos); 
		
		try 
		{
			dos.write(encoded);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		
		return bos.toByteArray();
	}
	
	/**
	 * private constructor so class cannot be instantiated by others
	 */
	private Utility() {
		// TODO Auto-generated constructor stub
	}

}
